package chapter21;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

/**
 * @author lzy
 * @version v1.0
 * Create DateTime: 2019/2/25 15:20
 */
public class SimpleMapper implements ISimpleMapper {

    private static void setFieldValue(Field field, Object object, String value) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class<?> type = field.getType();
        Object v;
        if (type == int.class) {
            v = Integer.parseInt(value);
        } else if (type == long.class) {
            v = Long.parseLong(value);
        } else if (type == float.class) {
            v = Float.parseFloat(value);
        } else if (type == double.class) {
            v = Double.parseDouble(value);
        } else if (type == boolean.class) {
            v = Boolean.parseBoolean(value);
        } else if (type == char.class) {
            v = value.charAt(0);
        } else if (type == String.class) {
            v = value;
        } else if (type == byte.class) {
            v = Byte.parseByte(value);
        } else if (type == short.class) {
            v = Short.parseShort(value);
        } else {
            Constructor<?> constructor = object.getClass().getConstructor(String.class);
            v = constructor.newInstance(value);
        }

        field.set(object, v);
    }

    @Override
    public String toString(Object object) {
        Class<?> clazz = object.getClass();
        StringBuilder builder = new StringBuilder();

        builder.append(clazz.getName()).append("\n");
        for (Field field : clazz.getDeclaredFields()) {
            if (!field.isAccessible()) {
                field.setAccessible(true);
            }
            try {
                builder.append(field.getName()).append("=").append(field.get(object)).append("\n");
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }

        return builder.toString();
    }

    @Override
    public Object toObject(String str) {
        BufferedReader reader = new BufferedReader(new StringReader(str));
        String line = null;
        Object result = null;
        Class<?> clazz = null;
        try {
            line = reader.readLine();
            clazz = Class.forName(line);
            result = clazz.newInstance();
        } catch (IOException | IllegalAccessException | InstantiationException | ClassNotFoundException e) {
            throw new RuntimeException(e);
        }

        try {
            while ((line = reader.readLine()) != null) {
                if (null == result) {
                    break;
                }
                String[] array = line.split("=");
                if (array.length < 2) {
                    continue;
                } else {
                    String fieldName = array[0];
                    String value = array[1];
                    Field field = clazz.getDeclaredField(fieldName);
                    if (field.getType().isPrimitive() || field.getType() == String.class) {
                        if (!field.isAccessible()) {
                            field.setAccessible(true);
                        }
                        setFieldValue(field, result, value);
                    }
                }
            }
        } catch (IOException | NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException | NoSuchFieldException e) {
            throw new RuntimeException(e);
        }
        return result;
    }
}
